"""
下载按钮识别器

专门用于识别和验证页面中的下载按钮，支持多种按钮样式和识别策略
实现任务3.1.1：下载按钮识别器
"""

import asyncio
import sys
from typing import Dict, Any, Optional, List
from playwright.async_api import Page, ElementHandle

# 添加项目根目录到路径
sys.path.append('k:/Projects/python/gamer520')

from src.browser.page_handler import BasePageHandler


class DownloadButtonRecognizer(BasePageHandler):
    """下载按钮识别器类"""
    
    def __init__(self, page: Page):
        super().__init__(page)
        
        # 特定的下载按钮选择器（基于实际页面结构）
        self.specific_selectors = [
            '#cao_widget_pay-4 > div.pay--content > div > a',  # 具体的页面结构选择器
            'a.go-down.btn.btn--secondary.btn--block',  # 基于class组合的选择器
            'a.go-down:has-text("立即下载")',  # 结合class和文本的选择器
            'a[class*="go-down"]:has-text("立即下载")',  # 更灵活的class匹配
        ]
        
        # 基于图标和文本组合的选择器
        self.icon_text_selectors = [
            'a:has(.fa-cloud-download):has-text("立即下载")',
            'button:has(.fa-cloud-download):has-text("立即下载")',
            'a:has(i[class*="download"]):has-text("立即下载")',
            'button:has(i[class*="download"]):has-text("立即下载")',
            'a:has(.fa-download):has-text("下载")',
            'button:has(.fa-download):has-text("下载")',
        ]
        
        # 文本匹配选择器
        self.text_selectors = [
            'button:has-text("立即下载")',
            'a:has-text("立即下载")',
            'button:has-text("下载游戏")',
            'a:has-text("下载游戏")',
            'button:has-text("免费下载")',
            'a:has-text("免费下载")',
            'button:has-text("下载")',
            'a:has-text("下载")',
        ]
        
        # CSS类名选择器
        self.class_selectors = [
            '.go-down',  # 特定class
            '.download-btn',
            '.download-button',
            '.btn-download',
            '.game-download',
            '.download-game',
            '.free-download',
            '.btn.btn--secondary.btn--block',  # 基于特定样式
        ]
        
        # 属性选择器
        self.attribute_selectors = [
            '[data-action="download"]',
            '[data-type="download"]',
            '[data-id*="download"]',
            'button[onclick*="download"]',
            'a[href*="download"]',
            'a[target="_blank"]:has-text("立即下载")',
            'a[target="_blank"]:has-text("下载")',
        ]
        
        # 通用选择器
        self.generic_selectors = [
            'button[class*="download"]',
            'a[class*="download"]',
            'button[id*="download"]',
            'a[id*="download"]',
            'a[class*="btn"][class*="secondary"]:has-text("下载")',
            'a[class*="go-down"]',
        ]
        
        # 所有选择器的优先级顺序
        self.all_selectors = (
            self.specific_selectors +
            self.icon_text_selectors +
            self.text_selectors +
            self.class_selectors +
            self.attribute_selectors +
            self.generic_selectors
        )
    
    async def handle(self) -> Dict[str, Any]:
        """
        处理下载按钮识别
        
        Returns:
            Dict: 处理结果，包含找到的下载按钮信息
        """
        try:
            # 查找下载按钮
            button_info = await self.find_download_button()
            
            if button_info:
                return {
                    'success': True,
                    'button_found': True,
                    'button_info': button_info,
                    'message': '成功找到下载按钮'
                }
            else:
                return {
                    'success': True,
                    'button_found': False,
                    'button_info': None,
                    'message': '未找到下载按钮'
                }
                
        except Exception as e:
            self.logger.error(f"下载按钮识别处理失败: {str(e)}")
            return {
                'success': False,
                'button_found': False,
                'button_info': None,
                'error': str(e),
                'message': '下载按钮识别处理失败'
            }

    async def find_download_button(self) -> Optional[Dict[str, Any]]:
        """
        查找下载按钮
        
        Returns:
            Dict: 下载按钮信息，包含element、selector、text等信息
        """
        try:
            self.logger.info("开始查找下载按钮...")
            
            # 1. 使用预定义选择器查找
            button_info = await self._find_by_selectors()
            if button_info:
                self.logger.info(f"通过选择器找到下载按钮: {button_info.get('selector')}")
                return button_info
            
            # 2. 智能搜索
            button_info = await self._smart_search()
            if button_info:
                self.logger.info(f"通过智能搜索找到下载按钮: {button_info.get('text')}")
                return button_info
            
            # 3. 深度搜索
            button_info = await self._deep_search()
            if button_info:
                self.logger.info(f"通过深度搜索找到下载按钮: {button_info.get('text')}")
                return button_info
            
            self.logger.warning("未找到任何下载按钮")
            return None
            
        except Exception as e:
            self.logger.error(f"查找下载按钮失败: {str(e)}")
            return None
    
    async def _find_by_selectors(self) -> Optional[Dict[str, Any]]:
        """
        使用预定义选择器查找下载按钮
        
        Returns:
            Dict: 按钮信息
        """
        try:
            for selector in self.all_selectors:
                try:
                    element = await self.page.query_selector(selector)
                    if element and await element.is_visible():
                        # 验证按钮是否可点击
                        is_enabled = await element.is_enabled()
                        if not is_enabled:
                            self.logger.debug(f"按钮不可点击，跳过: {selector}")
                            continue
                        
                        # 获取按钮详细信息
                        button_info = await self._get_button_info(element, selector)
                        
                        # 验证按钮有效性
                        if await self._validate_button(button_info):
                            self.logger.info(f"找到有效下载按钮: {selector}")
                            return button_info
                        else:
                            self.logger.debug(f"按钮验证失败: {selector}")
                            
                except Exception as e:
                    self.logger.debug(f"检查选择器 {selector} 失败: {str(e)}")
            
            return None
            
        except Exception as e:
            self.logger.error(f"选择器查找失败: {str(e)}")
            return None
    
    async def _smart_search(self) -> Optional[Dict[str, Any]]:
        """
        智能搜索下载按钮
        
        Returns:
            Dict: 按钮信息
        """
        try:
            # 查找所有可能的按钮和链接
            all_buttons = await self.page.query_selector_all('button, a, input[type="button"], input[type="submit"]')
            
            candidates = []
            
            for button in all_buttons:
                try:
                    if not await button.is_visible():
                        continue
                    
                    # 获取按钮信息
                    button_info = await self._get_button_info(button, 'smart_search')
                    
                    # 计算按钮匹配分数
                    score = await self._calculate_button_score(button_info)
                    
                    if score > 0:
                        button_info['score'] = score
                        candidates.append(button_info)
                        
                except Exception as e:
                    self.logger.debug(f"智能搜索按钮失败: {str(e)}")
            
            # 按分数排序，返回最高分的按钮
            if candidates:
                candidates.sort(key=lambda x: x.get('score', 0), reverse=True)
                best_candidate = candidates[0]
                
                if await self._validate_button(best_candidate):
                    self.logger.info(f"智能搜索找到最佳候选按钮，分数: {best_candidate.get('score')}")
                    return best_candidate
            
            return None
            
        except Exception as e:
            self.logger.error(f"智能搜索失败: {str(e)}")
            return None
    
    async def _deep_search(self) -> Optional[Dict[str, Any]]:
        """
        深度搜索下载按钮（最后的尝试）
        
        Returns:
            Dict: 按钮信息
        """
        try:
            # 搜索所有包含下载相关文本的元素
            download_texts = ['立即下载', '下载游戏', '免费下载', '下载', 'download', 'Download']
            
            for text in download_texts:
                try:
                    # 使用文本内容搜索
                    elements = await self.page.query_selector_all(f'*:has-text("{text}")')
                    
                    for element in elements:
                        try:
                            if not await element.is_visible():
                                continue
                            
                            tag_name = await element.evaluate('el => el.tagName.toLowerCase()')
                            
                            # 只考虑可点击的元素
                            if tag_name in ['button', 'a', 'input']:
                                button_info = await self._get_button_info(element, f'deep_search:{text}')
                                
                                if await self._validate_button(button_info):
                                    self.logger.info(f"深度搜索找到下载按钮: {text}")
                                    return button_info
                                    
                        except Exception as e:
                            self.logger.debug(f"深度搜索元素失败: {str(e)}")
                            
                except Exception as e:
                    self.logger.debug(f"深度搜索文本 {text} 失败: {str(e)}")
            
            return None
            
        except Exception as e:
            self.logger.error(f"深度搜索失败: {str(e)}")
            return None
    
    async def _get_button_info(self, element: ElementHandle, selector: str) -> Dict[str, Any]:
        """
        获取按钮详细信息
        
        Args:
            element: 按钮元素
            selector: 选择器
            
        Returns:
            Dict: 按钮信息
        """
        try:
            return {
                'element': element,
                'selector': selector,
                'text': await element.text_content() or '',
                'inner_text': await element.inner_text() or '',
                'href': await element.get_attribute('href'),
                'onclick': await element.get_attribute('onclick'),
                'data_action': await element.get_attribute('data-action'),
                'data_id': await element.get_attribute('data-id'),
                'target': await element.get_attribute('target'),
                'position': await element.bounding_box(),
                'is_enabled': await element.is_enabled(),
                'is_visible': await element.is_visible(),
                'tag_name': await element.evaluate('el => el.tagName.toLowerCase()'),
                'class_name': await element.get_attribute('class') or '',
                'id': await element.get_attribute('id') or '',
            }
        except Exception as e:
            self.logger.error(f"获取按钮信息失败: {str(e)}")
            return {
                'element': element,
                'selector': selector,
                'text': '',
                'error': str(e)
            }
    
    async def _calculate_button_score(self, button_info: Dict[str, Any]) -> int:
        """
        计算按钮匹配分数
        
        Args:
            button_info: 按钮信息
            
        Returns:
            int: 匹配分数（越高越好）
        """
        try:
            score = 0
            text = button_info.get('text', '').lower().strip()
            class_name = button_info.get('class_name', '').lower()
            
            # 文本匹配评分
            if '立即下载' in text:
                score += 100  # 最高分
            elif '下载游戏' in text:
                score += 90
            elif '免费下载' in text:
                score += 85
            elif '下载' in text:
                score += 70
            elif 'download' in text:
                score += 60
            
            # class名称评分
            if 'go-down' in class_name:
                score += 50
            elif 'btn--secondary' in class_name and 'btn--block' in class_name:
                score += 45
            elif 'download' in class_name:
                score += 40
            elif 'btn' in class_name:
                score += 20
            
            # 属性评分
            if button_info.get('target') == '_blank':
                score += 15
            
            if button_info.get('data_id'):
                score += 10
            
            # 图标评分
            if button_info.get('element'):
                try:
                    if await self._has_download_icon(button_info['element']):
                        score += 30
                except:
                    pass
            
            return score
            
        except Exception as e:
            self.logger.debug(f"计算按钮分数失败: {str(e)}")
            return 0
    
    async def _has_download_icon(self, element: ElementHandle) -> bool:
        """
        检查元素是否包含下载图标
        
        Args:
            element: 元素
            
        Returns:
            bool: 是否包含下载图标
        """
        try:
            icon_selectors = [
                'i.fa-cloud-download',
                'i.fa-download',
                'i[class*="download"]',
                '.fa-cloud-download',
                '.fa-download',
                '[class*="download-icon"]',
                'svg[class*="download"]',
                '.icon-download'
            ]
            
            for selector in icon_selectors:
                icon = await element.query_selector(selector)
                if icon:
                    return True
            
            return False
            
        except Exception as e:
            self.logger.debug(f"检查下载图标失败: {str(e)}")
            return False
    
    async def _validate_button(self, button_info: Dict[str, Any]) -> bool:
        """
        验证按钮是否为有效的下载按钮
        
        Args:
            button_info: 按钮信息
            
        Returns:
            bool: 是否有效
        """
        try:
            text = button_info.get('text', '').lower().strip()
            class_name = button_info.get('class_name', '').lower()
            tag_name = button_info.get('tag_name', '')
            
            # 基本可见性和可用性检查
            if not button_info.get('is_visible') or not button_info.get('is_enabled'):
                return False
            
            # 高优先级验证：特定的按钮样式
            if '立即下载' in text:
                return True
            
            if 'go-down' in class_name:
                return True
            
            if 'btn--secondary' in class_name and 'btn--block' in class_name:
                return True
            
            # 中等优先级验证：通用下载特征
            download_keywords = ['下载', 'download', '获取', 'get', '安装', 'install']
            if any(keyword in text for keyword in download_keywords):
                # 进一步验证
                href = button_info.get('href')
                onclick = button_info.get('onclick')
                
                if href or onclick or tag_name in ['button', 'a']:
                    return True
            
            # 低优先级验证：基于class的验证
            download_class_keywords = ['download', 'btn', 'button', 'go-down']
            if any(keyword in class_name for keyword in download_class_keywords):
                return True
            
            return False
            
        except Exception as e:
            self.logger.debug(f"验证按钮失败: {str(e)}")
            return False
    
    async def click_download_button(self, button_info: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """
        点击下载按钮
        
        Args:
            button_info: 按钮信息，如果为None则自动查找
            
        Returns:
            Dict: 点击结果
        """
        try:
            if not button_info:
                button_info = await self.find_download_button()
            
            if not button_info:
                return {'success': False, 'error': '未找到下载按钮'}
            
            element = button_info['element']
            
            # 滚动到按钮位置
            await element.scroll_into_view_if_needed()
            await asyncio.sleep(0.5)
            
            # 点击按钮
            await element.click()
            self.logger.info(f"成功点击下载按钮: {button_info.get('text', 'Unknown')}")
            
            # 等待页面响应
            await asyncio.sleep(1)
            
            return {
                'success': True,
                'button_text': button_info.get('text'),
                'button_selector': button_info.get('selector'),
                'button_class': button_info.get('class_name'),
                'click_timestamp': asyncio.get_event_loop().time()
            }
            
        except Exception as e:
            self.logger.error(f"点击下载按钮失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    async def get_button_status(self) -> Dict[str, Any]:
        """
        获取页面中下载按钮的状态信息
        
        Returns:
            Dict: 状态信息
        """
        try:
            button_info = await self.find_download_button()
            
            if button_info:
                return {
                    'has_download_button': True,
                    'button_text': button_info.get('text'),
                    'button_selector': button_info.get('selector'),
                    'button_class': button_info.get('class_name'),
                    'is_clickable': button_info.get('is_enabled'),
                    'position': button_info.get('position')
                }
            else:
                return {
                    'has_download_button': False,
                    'message': '未找到下载按钮'
                }
                
        except Exception as e:
            self.logger.error(f"获取按钮状态失败: {str(e)}")
            return {
                'has_download_button': False,
                'error': str(e)
            }